'######################################################################################
'Author  :         Sumit Gupta 
'Company :				 Vikasumit
'Date    :         9th July 2005
'--------------------------------------------------------------------------------------
'Working / Note on File : 
'This File contains the Piece Class and Related Enumeration used with this class
'It Define a Single Piece as Stand alone Entity and its Attributes, It may or may not
'have any graphics related to it there fore the attribute of graphics is not attach
'to this class.

'It validate the piece movement with respect to standard chess game. Each Move function 
'is Overridable for the Child class to override the movement of the chess game
'######################################################################################

Imports System.Math
Imports VSUtility

'Enumeration for the Piece Type
'NOTE: If a New Piece type is require you can Append this list
Public Enum enPieceType
	PTNull = 0
	PTPawn = 1
	PTRook = 2
	PTBishop = 3
	PTKnight = 4
	PTCounselor = 5
	PTKing = 6
End Enum


'Enumeration for the Piece Color
'NOTE: If a New Piece Color is require you can Append this list
Public Enum enPieceColor
	PCNULL = 0
	PCBlack = 1
	PCWhite = 2
End Enum


' Class for the Pieces
Public Class clsPiece


	'Member Data Section


#Region "Private Temparory Varibles for Properties"
  Private Const CON_CLASSVERSION As String = "1.0.20050709" 'Define the Class Version
	Private t_Color As enPieceColor
	Private t_Type As enPieceType
	Private Log As clsLog
	Private t_Dologging As Boolean
#End Region

#Region "Public Property"

	'Get the Class Version
	Public ReadOnly Property ClassVersion() As String
		Get
			Return CON_CLASSVERSION
		End Get
	End Property

	'Piece Type
	Public Property Type() As enPieceType
		Get
			Return t_Type
		End Get
		Set(ByVal Value As enPieceType)
			t_Type = Value
		End Set
	End Property

	'Piece Color
	Public Property Color() As enPieceColor
		Get
			Return t_Color
		End Get
		Set(ByVal Value As enPieceColor)
			t_Color = Value
		End Set
	End Property

	Public Property DoLogging() As Boolean
		Get
			Return t_Dologging
		End Get
		Set(ByVal Value As Boolean)
			t_Dologging = Value
			Log.DoLogging = t_Dologging
		End Set
	End Property

#End Region


	'Member Functions


#Region "Private Move Function"

	'Function to Initialize
	Private Sub Initialize()
		t_Dologging = False
		Log = New clsLog("Piece_Class", Me.ClassVersion)
		Log.AddDateTimeStamp = True
		Log.DoLogging = t_Dologging
	End Sub

	'Move of a Rook
	Private Function MoveRook(ByVal curPos As clsPosition, ByVal newPos As clsPosition) As Boolean
		If (curPos.X = newPos.X And curPos.Y <> newPos.Y) _
		 Or (curPos.Y = newPos.Y And curPos.X <> newPos.X) Then
			Return True
		Else
			Return False
		End If
	End Function

	'Move of  Bishop
	Private Function MoveBishop(ByVal curPos As clsPosition, ByVal newPos As clsPosition) As Boolean
		'Bishop Moves Diagonal
		If Abs(curPos.X - newPos.X) = Abs(curPos.Y - newPos.Y) Then
			Return True
		Else
			Return False
		End If
	End Function

	'Move of Kinight
	Private Function MoveKnight(ByVal curPos As clsPosition, ByVal newPos As clsPosition) As Boolean
		If (newPos.X = curPos.X + 2 And newPos.Y = curPos.Y + 1) Then Return True
		If (newPos.X = curPos.X + 1 And newPos.Y = curPos.Y + 2) Then Return True
		If (newPos.X = curPos.X - 2 And newPos.Y = curPos.Y - 1) Then Return True
		If (newPos.X = curPos.X - 1 And newPos.Y = curPos.Y - 2) Then Return True
		If (newPos.X = curPos.X + 2 And newPos.Y = curPos.Y - 1) Then Return True
		If (newPos.X = curPos.X + 1 And newPos.Y = curPos.Y - 2) Then Return True
		If (newPos.X = curPos.X - 2 And newPos.Y = curPos.Y + 1) Then Return True
		If (newPos.X = curPos.X - 1 And newPos.Y = curPos.Y + 2) Then Return True
	End Function

	'Move of Pawn
	Private Function MovePawn(ByVal curPos As clsPosition, ByVal newPos As clsPosition) As Boolean

		Select Case Me.Color
			Case enPieceColor.PCWhite
				'Pawn can not get back to first lines 
				If newPos.X = 0 Then
					Return False
				End If
				'Check that if the New pos is One less in y coordinate of
				'currnet position or a side attack move is given
				If ((newPos.X = curPos.X + 1) And newPos.Y = curPos.Y) Or _
				(newPos.X = curPos.X + 1 And (newPos.Y = curPos.Y + 1 Or newPos.Y = curPos.Y - 1)) Then
					Return True
					'Two step movement for the First move only
        ElseIf newPos.X = curPos.X + 2 And curPos.X = 1 And newPos.Y = curPos.Y Then
          Return True
        Else
          'Invalid turn
          Return False
        End If
			Case enPieceColor.PCBlack
				'Pawn can not get back to initial lines 
				If newPos.X = 7 Then
					Return False
				End If
				'Check that if the New pos is One less in y coordinate of currnet position 
				'or a side attack move is given
				If ((newPos.X = curPos.X - 1) And newPos.Y = curPos.Y) Or _
				(newPos.X = curPos.X - 1 And (newPos.Y = curPos.Y + 1 Or _
				newPos.Y = curPos.Y - 1)) Then
					Return True
					'Two step movement for the First move only
        ElseIf newPos.X = curPos.X - 2 And curPos.X = 6 And newPos.Y = curPos.Y Then
          Return True
        Else
          'Invalid turn
          Return False
        End If
		End Select

	End Function

	'Move of Queen
	Private Function MoveQueen(ByVal curPos As clsPosition, ByVal newPos As clsPosition) As Boolean
		If (curPos.X = newPos.X And curPos.Y <> newPos.Y) _
		 Or (curPos.Y = newPos.Y And curPos.X <> newPos.X) Then
			Return True
		ElseIf Abs(curPos.X - newPos.X) = Abs(curPos.Y - newPos.Y) Then
			Return True
		Else
			Return False
		End If
	End Function

	'Move of King
	Private Function MoveKing(ByVal curPos As clsPosition, ByVal newPos As clsPosition) As Boolean
    'TODO: Put a check for Castling here
    If newPos.X >= curPos.X - 1 And newPos.X <= curPos.X + 1 And _
    newPos.Y >= curPos.Y - 1 And newPos.Y <= curPos.Y + 1 Then
      Return True
    ElseIf curPos.Y = newPos.Y AndAlso (curPos.X + 2 = newPos.X OrElse _
    newPos.X = curPos.X - 2) Then
      Return True   'Add for the Castle Move (It allow a king to move to the Castle move)
      'Other checks are handle by Board not by this
    Else
      Return False
    End If

	End Function

#End Region

#Region "Public Function"

	'Sub to Change the Piece Data
  Public Sub CopyAs(ByVal piece As clsPiece)
    Me.Color = piece.Color
    Me.Type = piece.Type
    Me.DoLogging = piece.DoLogging
  End Sub

	'Check the Null Value
	Public Function IsNull() As Boolean
		If t_Color = enPieceColor.PCNULL AndAlso t_Type = enPieceType.PTNull Then
			Return True
		Else
			Return False
		End If
	End Function

	'Compare
	Public Function IsEqualTo(ByVal Piece As clsPiece) As Boolean
		If t_Color = Piece.Color AndAlso t_Type = Piece.Type Then
			Return True
		Else
			Return False
		End If
	End Function

	'Compare by direct data
	Public Function IsEqualTo(ByVal color As enPieceColor, ByVal type As enPieceType) As Boolean
		If t_Color = color AndAlso t_Type = type Then
			Return True
		Else
			Return False
		End If
	End Function

	'Compare by direct data
	Public Function IsEqualTo(ByVal type As enPieceType, ByVal color As enPieceColor) As Boolean
		If t_Color = color AndAlso t_Type = type Then
			Return True
		Else
			Return False
		End If
	End Function

	'Function to validate the position of the Piece
	Public Function Move_Validator(ByVal curPos As clsPosition, ByVal newPos As clsPosition) As Boolean
		Log.Write("In Move Validator")
		Select Case Me.Type
			Case enPieceType.PTBishop
        Return MoveBishop(curPos, newPos)
			Case enPieceType.PTCounselor
				Return MoveQueen(curPos, newPos)
			Case enPieceType.PTKing
				Return MoveKing(curPos, newPos)
			Case enPieceType.PTKnight
				Return MoveKnight(curPos, newPos)
			Case enPieceType.PTNull
				Return False
			Case enPieceType.PTPawn
				Return MovePawn(curPos, newPos)
			Case enPieceType.PTRook
				Return MoveRook(curPos, newPos)
		End Select

	End Function

#End Region

#Region "Constructor"

	'Default
	Public Sub New()
		t_Color = enPieceColor.PCNULL
		t_Type = enPieceType.PTNull
		Initialize()
	End Sub

	'From Values
	Public Sub New(ByVal MyColor As enPieceColor, ByVal MyType As enPieceType)
		t_Color = MyColor
		t_Type = MyType
		Initialize()
	End Sub

	'From Values
	Public Sub New(ByVal MyType As enPieceType, ByVal MyColor As enPieceColor)
		t_Color = MyColor
		t_Type = MyType
		Initialize()
	End Sub

	'Copy
	Public Sub New(ByVal Piece As clsPiece)
		t_Color = Piece.Color
		t_Type = Piece.Type
		Initialize()
	End Sub

#End Region

End Class